#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFileDialog>
#include <QStandardItemModel>
#include <iostream>
#include "geometrydata.h"
#include "loader.h"
#include <QThread>
#include "scenevisualizer.h"
#include "meshitem.h"
#include <QGLWidget>
#include "config.h"
#include "saver.h"
#include "pointitem.h"
#include "contouritem.h"
#include "cmath.h"
#include "triangletreemodel.h"
#include "QTreeWidget"
#include <QDoubleSpinBox>
#include "ccalculation.h"

//===========================================================
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->progressBar->hide();

    view = new MyGraphView();
    scene = new SceneVisualizer;
    QWidget *glwid = new QWidget();
                //QGLFormat(QGL::SingleBuffer));

    view->setViewport(glwid);
    view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    view->setScene(scene);
    treeWidget = new QTreeWidget;
    treemodel = new TriangleTreeModel(treeWidget);
    ui->horizontalLayout_3->addWidget(treeWidget);

    view->setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
                                      | QGraphicsView::DontClipPainter
                                      | QGraphicsView::DontSavePainterState);
    //ui->EditorWidget = new
    ui->horizontalLayout->addWidget(view);
    connect(view, SIGNAL(meshItemSelected(MeshItem *)), this, SLOT(onMeshItemSelected(MeshItem*)));//, Qt::QueuedConnection);
}

//===========================================================
void MainWindow::onOpenDefault()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),"",tr("Files (*.*)"));
    std::cout<<fileName.toStdString()<<std::endl;
    data.clear();
    scene->clear();
    std::cout<<"Start oad"<<std::endl;
    startLoad(fileName);
}

//===========================================================
void MainWindow::startLoad(QString fileName)
{
    loader = new Loader(fileName, &data);
    loader->moveToThread(&loader_thread);

    connect(&loader_thread, SIGNAL(started()), loader, SLOT(load()), Qt::DirectConnection);
    connect(loader, SIGNAL(progressChanged(int, QString)), this, SLOT(progressChanged(int, QString)), Qt::QueuedConnection);
    connect(loader, SIGNAL(finished()), this, SLOT(stopLoad()), Qt::QueuedConnection);

    std::cout<<"Start oad2"<<std::endl;
    loader_thread.start();
    std::cout<<"Start oad3"<<std::endl;
    ui->progressBar->show();
    ui->progressBar->setValue(0);

}

//===========================================================
void MainWindow::stopLoad()
{
    loader_thread.terminate();
    loader_thread.wait();
    delete loader;

    vizualizeScene();

    ui->progressBar->hide();
    ui->statusBar->showMessage("Trinagles: "+QString::number(data.triangles.size()) + " Points: "+QString::number(data.points.size()),-1);
}

//===========================================================
void MainWindow::vizualizeScene()
{
    int prev_progress= 0;
    int progress = 0;

    progressChanged(progress, "Visualizating scene");

    if (data.type() == GeometryData::TRIANGLES)
    for (int  i =0; i < data.triangles.size(); i++ )
    {
        MeshItem *it = new MeshItem(data.triangles[i]);
        scene->addItem(it);

        progress = ((double)i / (double)data.triangles.size()) * 100;
        if (progress > prev_progress)
        {
            prev_progress = progress;
            progressChanged(progress,"Visualizating scene");
        }
    }

    if (data.type() == GeometryData::POINTS)
    for (int  i =0; i < data.points.size(); i++ )
    {

        PointItem *it = new PointItem(data.points[i]);
        scene->addItem(it);

        progress = ((double)i / (double)data.points.size()) * 100;
        if (progress > prev_progress)
        {
            prev_progress = progress;
            progressChanged(progress,"Visualizating scene");
        }
    }

    if (data.type() == GeometryData::CONTOURS)

    for (int  i =0; i < data.contours.size(); i++ )
    {

        ContourItem *it = new ContourItem(data.contours[i]);
        scene->addItem(it);

        progress = ((double)i / (double)data.contours.size()) * 100;
        if (progress > prev_progress)
        {
            prev_progress = progress;
            progressChanged(progress,"Visualizating scene");
        }
    }

    view->fitInView(scene->itemsBoundingRect(),Qt::KeepAspectRatio);
}

//===========================================================
void MainWindow::onInitialTriangulation()
{
   std::string algo;
   if (QObject::sender() == ui->actionP2t)
       algo = "p2t";
   if (QObject::sender() == ui->actionMy)
       algo = "my";

   data.triangulateContours(algo);
   scene->clear();

   vizualizeScene();
}

//===========================================================
void MainWindow::onSharpTriangulation()
{
   std::string algo;
   if (QObject::sender() == ui->actionByArea)
       algo = "area";
   if (QObject::sender() == ui->actionOnce)
       algo = "once";
   if (QObject::sender() == ui->actionByLength)
       algo = "length";

   data.sharpTriangulation(algo);
   scene->clear();

   vizualizeScene();
}
//===========================================================
void MainWindow::onDoCalculation()
{
    CCalculation calc(&data);
    calc.doCalculation();
}

//===========================================================
void MainWindow::onEnableColor(bool flag)
{
    Config::enableColorMesh(flag);
    scene->update();
}

//===========================================================
void MainWindow::onEnableText(bool flag)
{
    Config::enableInfoText(flag);
    scene->update();
}

void MainWindow::onEnableGrid(bool flag)
{
    Config::enableGrid(flag);
    scene->update();
}

void MainWindow::onEnableMesh(bool flag)
{
    Config::enableMesh(flag);
    scene->update();
}

void MainWindow::progressChanged(int progress,QString message)
{
    ui->progressBar->setFormat(message+" %p%");
    ui->progressBar->setValue(progress);
}

void MainWindow::onMeshItemSelected(MeshItem *it)
{
    treemodel->set(it->trg());

    //connect(tree, SIGNAL( itemChanged ( QTreeWidgetItem * , int ), this, SLOT(QTreeWidgetItem * , int)));

}

void MainWindow::onPointValueChanged(double val)
{
  /*  if (QObject::sender() == ui->p1X)
        view->selectedItem()->trg()->p1->x = val;

    if (QObject::sender() == ui->p1Y)
        view->selectedItem()->trg()->p1->y = val;

    if (QObject::sender() == ui->p2X)
        view->selectedItem()->trg()->p2->x = val;

    if (QObject::sender() == ui->p2Y)
        view->selectedItem()->trg()->p2->y = val;

    if (QObject::sender() == ui->p3X)
        view->selectedItem()->trg()->p3->x = val;

    if (QObject::sender() == ui->p3Y)
        view->selectedItem()->trg()->p3->y = val;

    view->selectedItem()->updateParams();
    scene->update();*/
}

void MainWindow::onParamValueChanged(int val)
{
    view->selectedItem()->trg()->param = val;
    view->selectedItem()->updateParams();
    scene->update();
}

void MainWindow::onSave()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),"",tr("Files (*.dat)"));
    std::cout<<fileName.toStdString()<<std::endl;
    startSave(fileName);
}

void MainWindow::startSave( QString filename)
{
    saver = new Saver(filename, &data);
    saver->moveToThread(&loader_thread);

    connect(&loader_thread, SIGNAL(started()), saver, SLOT(save()), Qt::DirectConnection);
    connect(saver, SIGNAL(progressChanged(int, QString)), this, SLOT(progressChanged(int, QString)), Qt::QueuedConnection);
    connect(saver, SIGNAL(finished()), this, SLOT(stopSave()), Qt::QueuedConnection);

    loader_thread.start();
    ui->progressBar->show();
    ui->progressBar->setValue(0);
}

void MainWindow::stopSave()
{
    loader_thread.terminate();
    loader_thread.wait();
    delete saver;

    vizualizeScene();

    ui->progressBar->hide();
}

void MainWindow::onAutoBounds()
{
    data.autoBound();
}

MainWindow::~MainWindow()
{
    delete ui;
}


